'''
Created on January 11, 2010

This Module has all classes and functions responsible for network-related
configuration. Like query or assign an IP address and setting the default
gateway or name servers.
'''

import os
import subprocess

class NetworkConfig(object) :
    '''Handles Network configuration related tasks.'''
    
    def __init__(self) :
        pass
    
    
    def getIntrInfo(self, interface):
        """
        get specefic interface info
        """
        process = os.popen('ifconfig '+interface).read()
        return process
    
    
    def getInterfaces(self):
        '''
        getInterfaces()
        return a list of all network interfaces.
        '''
        process = os.popen('ifconfig -a |grep "Link encap" |cut -d" " -f1')
        ifaceList = process.read().strip().split('\n')
        process.close()
        
        return ifaceList
        
        
    def getInfo(self):
        """
        list network information.
        """
        networkInfo = os.popen("ifconfig -a").read()
        
        return networkInfo
        
        
    def getIP (self, interface) :
        """
        return the IP address for the selected interface.
        WORKS WITH IPV4 ONLY.
        """
        
        # declaring variables.
        ipAddress = ""
        subnetMask = ""
        broadcastAddress = ""
        
        # execute "ifconfig" and split the lines into a list.
        ifconfigOutput = os.popen("ifconfig").read().splitlines()
        
        # loop over the lines in the output of the "ifconfig" command.
        for i in range(len(ifconfigOutput)) :
            
            # split the line into words.
            tempLine = ifconfigOutput[i].split()
            
            # if the line is not empty.
            if tempLine :
                
                # if the first word is interface name. 
                if tempLine[0] == interface :
                    
                    # the line that has the IP address is the next one after that.
                    # if the line starts with the word "inet", then it has the IP address.
                    if ifconfigOutput[i+1].strip().find("inet") == 0 :
                        
                        # split the IP info line into words.
                        ipInfo = ifconfigOutput[i+1].strip().split()
                        
                        # loop over the words on the IP info line.
                        for option in ipInfo :
                            
                            # extract the IP address.
                            if option.find("addr") == 0 :
                                ipAddress = option[option.index(":") +1 :]
                            
                            # extract the broadcast address. 
                            elif option.find("Bcast") == 0 :
                                broadcastAddress = option[option.index(":") +1 :]
                            
                            # extract the Net Mask.
                            elif option.find("Mask") == 0 :
                                subnetMask = option[option.index(":") +1 :]
                        
                        # break out the loop after extracting the IP info.
                        break
                    
                    # if the next line after the interface name doesn't start with "inet"
                    # then this interface doesn't have an IPv4 address on it, return None.
                    else :
                        return None
        
        # return a tuple that has the IP info, if exists.
        if ipAddress :
            return (ipAddress, subnetMask, broadcastAddress)
    
    
    def setIP (self, interface, newIP = None, subnetMask = None) :
        """
        Assign the passed IP address on the requested interface, if no IP address passed,
        it will attempt to get it via DHCP.
        """
        
        # if no IP address passed, attempt to get it via DHCP.
        if newIP is None :
            if subprocess.call("dhclient " + interface, shell = True) :
                
                # return False if failed.
                return False
            
            # return true if succeeded. 
            else :
                return True
        
        # if an IP address and a subnet mask are passed, assign the IP address
        # to the interface manually.
        elif subnetMask is not None :
            
            # calling the "ifconfig" command to assign the ip address to the interface.
            if subprocess.call("ifconfig " + interface + " " + newIP + \
                               " netmask " + subnetMask, shell = True) :
                
                # return False if failed.
                return False
            
            # return True if succeeded.
            else :
                return True
        
        # if no subnet mask is passed, raise a ValueError 
        else :
            raise ValueError, "No subnet mask entered"
    
    
    def setGateway (self, gatewayIP) :
        """
        Set the default gateway.
        """
        
        # loop until all default gateways are deleted.
        while True :
            
            returnCode = subprocess.call("route del -net default 2> /dev/null", shell = True)
            
            # if no error returned  while deleting the route, continue.
            if returnCode == 0:
                continue
            
            # if an error returned while deleting the route, break the loop.
            else :
                break
        
        # add the default gateway, after deleting all default gateways.
        if subprocess.call("route add default gw " + gatewayIP, shell = True) :
            
            # if an error returned, return False.
            return False
        
        # if no errors returned, return True.
        else :
            return True
    
    
    def setDNS (self, primaryDNS, secondaryDNS) :
        """
        Set's the name servers.
        """
        
        # add the primary name server to /etc/resolv.conf
        if subprocess.call("echo nameserver " + primaryDNS + " > /etc/resolv.conf", shell = True) :
            return False
        
        # add the secondary name server to /etc/resolv.conf
        if subprocess.call("echo nameserver " + secondaryDNS + " >> /etc/resolv.conf", shell = True) :
            return False
        
        # if succeeded to add both primary and secondary name servers, return True.
        else :
            return True
    

def main():
    
    # THE FOLLOWING CODE IS JUST FOR TESTING
    # CODER DISCRITION IS ADVISED :D
    x = NetworkConfig()
    print x.getIntrInfo("eth0")
#    print x.getIP("eth0")
#    
#    #if x.setIP("eth0", "10.0.0.5", "255.255.0.0") :
#    if x.setIP("eth0", "192.168.1.55", "255.255.255.0") :
#        print "IP address changed successfully"
#        print x.getIP("eth0")
#    else :
#        print "failed to change IP address"
        
#    if x.setGateway("10.0.0.3") :
#        print "succeeded to change the default gateway"
#    
#    else :
#        print "failed to change the default gateway"
#    
#    if x.setDNS("1.1.1.1", "2.2.2.2") :
#        print "succeeded to add name servers"
#    
#    else :
#        print "failed to to add name servers"

if __name__ == "__main__" :
    main()
    # call the main() function here to test the module
    #pass
